package org.mspring.mlog.biz;

import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import java.io.InputStream;

/**
 * 七牛服务的封装
 *
 * @author Gao Youbo
 * @since 2014-12-30 15:37
 */
public class QiniuService {

    private static final Logger LOG = LoggerFactory.getLogger(QiniuService.class);

    private String accessKey;
    private String secretKey;
    private String bucket;
    private String domain;


    //密钥配置
    private Auth auth;
    //创建上传对象
    private UploadManager uploadManager;

    @PostConstruct
    void init() {
        auth = Auth.create(accessKey, secretKey);
        uploadManager = new UploadManager();
    }

    public UploadResult upload(InputStream inputStream) {
        try {
            byte[] bytes = IOUtils.toByteArray(inputStream);
            return upload(bytes);
        } catch (Exception e) {
            LOG.error("上传文件失败", e);
        }
        return null;
    }

    public UploadResult upload(byte[] data) {
        try {
            String key = DigestUtils.md5Hex(data);
            String token = getUpToken(key);
            Response response = uploadManager.put(data, key, token);
            return UploadResult.from(domain, response);
        } catch (QiniuException e) {
            return UploadResult.from(domain, e.response);
        }
    }

    // 覆盖上传
    private String getUpToken(String key) {
        //<bucket>:<key>，表示只允许用户上传指定key的文件。在这种格式下文件默认允许“修改”，已存在同名资源则会被本次覆盖。
        //如果希望只能上传指定key的文件，并且不允许修改，那么可以将下面的 insertOnly 属性值设为 1。
        //第三个参数是token的过期时间
        return auth.uploadToken(bucket, key, 3600, new StringMap().put("insertOnly", 1));
    }

    public static class UploadResult {
        private boolean success;
        private String key;
        private String hash;
        private String url;

        public static UploadResult from(String domain, Response response) {
            if (StringUtils.isBlank(domain)) {
                throw new IllegalArgumentException("domain不能为空");
            }
            UploadResult ret = new UploadResult();
            ret.setSuccess(response.isOK());
            if (ret.isSuccess()) {
                try {
                    StringMap map = response.jsonToMap();
                    String key = String.valueOf(map.get("key"));
                    String hash = String.valueOf(map.get("hash"));
                    ret.setKey(key);
                    ret.setHash(hash);
                    ret.setUrl(makeUrl(domain, key));
                } catch (Exception e) {
                    LOG.error(null, e);
                }
            }
            return ret;
        }

        private static String makeUrl(String domain, String key) {
            StringBuilder sb = new StringBuilder();
            sb.append("http://").append(domain).append("/").append(key);
            return sb.toString();
        }

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getHash() {
            return hash;
        }

        public void setHash(String hash) {
            this.hash = hash;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public void setBucket(String bucket) {
        this.bucket = bucket;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }
}
